#ifndef _PASE_PARAM_H_
#define _PASE_PARAM_H_

typedef int PC_TYPE;
#define PRECOND_NONE -1
#define PRECOND_A -2
#define PRECOND_B -3
#define PRECOND_B_A -4

typedef const char *SMOOTHING_TYPE;
#define PASE_BCG "bcg"
#define PASE_DIRECT "direct"

typedef const char *MULTIGRID_TYPE;
#define PASE_AMG "amg"
#define PASE_GMG "gmg"

typedef const char *BOUNDARY_TYPE;
#define PASE_DIRICHLET "dirichlet"

typedef const char *PASE_TYPE;
#define PASE_DEFAULT "default"
#define PASE_MOVING "moving"
#define PASE_TWOLEVEL "two-level"

#include <stdbool.h>
#include "mpi.h"

/* parameters that can be modified by the user */
typedef struct PASE_PARAMETER_PRIVATE_
{
    /* params about levels */
    int num_levels;
    /* params about problem */
    void *A, *B;
    void **A_array;
    void **B_array;
    void **P_array;
    int nev;      // pase 当成多少算
    int real_nev; // 实际上多少收敛就停
    int num_given_eigs;
    MULTIGRID_TYPE multigrid_type;
    /* params about pase */
    PASE_TYPE solver_type;
    int aux_coarse_level;
    int aux_fine_level;
    int max_cycle_count;
    double rtol;
    /* params about smoothing */
    SMOOTHING_TYPE smoothing_type;
    int max_pre_count, max_post_count;
    /* params about initial GCGE */
    int initial_level;
    int max_initial_direct_count;
    double initial_atol;
    double initial_rtol;
    /* params about aux GCGE */
    int max_direct_count;
    double aux_atol;
    double aux_rtol;
    double max_aux_rtol;
    double aux_rtol_coef;
    /* params about GMG */
    BOUNDARY_TYPE boundary_type;
    bool boundary_delete;
    int boundary_num;
    int *boundary_index;
    /* params about precondition */
    PC_TYPE pc_type;
    bool pc_eigendcp;
    /* params about print */
    int print_level;
    /* 分组分批 */
    bool if_groups, if_batches;
    bool *convergence_status; // 用来判断每个向量收敛与否
    int group_num;            // process group
    int group_id;
    MPI_Group group;
    MPI_Comm group_comm;
    int batch_size; // for each batch
    int more_batch_size;
    int more_aux_nev;
    // 接口用
    bool if_error_estimate;
    void **initial_solution;
    void *A_pre, *B_pre, *shift_pre;
} PASE_PARAMETER_PRIVATE;

typedef PASE_PARAMETER_PRIVATE *PASE_PARAMETER;

void PASE_PARAMETER_Create(PASE_PARAMETER *param, int num_levels, int nev, double rtol, MULTIGRID_TYPE type);

void PASE_PARAMETER_Destroy(PASE_PARAMETER *param);

void PASE_PARAMETER_Get_from_command_line(PASE_PARAMETER param, int argc, char *argv[]);


void PASE_PARAMETER_CREATE(PASE_PARAMETER *param, int num_levels, int nev, double rtol, MULTIGRID_TYPE type);
#endif
